﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MarvellousWorks.PracticalPatternNet8.Concept.Generics;

public interface IAttributeBuilder
{
    IList<string> Log { get; }
    void BuildPartA();
    void BuildPartB();
    void BuildPartC();
    void BuildPartD();
}

[Director(1, nameof(BuildPartA))]
[Director(2, nameof(BuildPartB))]
[Director(3, nameof(BuildPartC))]
[Director(4, nameof(BuildPartD))]
public class AttributeBuilder : IAttributeBuilder
{
    public IList<string> Log { get; } = new List<string>();
    public void BuildPartA()
    {
        Log.Add("Building Part A");
    }
    public void BuildPartB()
    {
        Log.Add("Building Part B");
    }
    public void BuildPartC()
    {
        Log.Add("Building Part C");
    }
    public void BuildPartD()
    {
        Log.Add("Building Part D");
    }
}

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class DirectorAttribute : Attribute, IComparable<DirectorAttribute>
{
    private readonly int _priority;
    private readonly string _method;

    public DirectorAttribute(int priority, string method)
    {
        _priority = priority;
        _method = method;
    }
    public int Priority { get { return _priority; } }
    public string Method { get { return _method; } }

    /// <summary>
    /// 提供按照优先级比较的 ICompare<T> 实现，
    /// </summary>
    /// <param name="other"></param>
    /// <returns></returns>
    public int CompareTo(DirectorAttribute? other)
    {
        return other._priority - this._priority;
    }
}

public class Director
{
    public void BuildUp(IAttributeBuilder builder)
    {
        //if (builder == null) throw new ArgumentNullException(nameof(builder));
        //builder.BuildPartA();
        //builder.BuildPartB();
        //builder.BuildPartC();

        // 获取 Builder 的 DirectorAttribute 属性
        var attributes = builder.GetType().GetCustomAttributes(typeof(DirectorAttribute), false)
            .Cast<DirectorAttribute>().OrderBy(attr => attr.Priority).ToList();

        // 按照优先级执行方法
        foreach (var attribute in attributes)
        {
            var method = builder.GetType().GetMethod(attribute.Method);
            if (method != null)
            {
                method.Invoke(builder, null);
            }
            else
            {
                throw new InvalidOperationException($"Method {attribute.Method} not found on {builder.GetType().Name}");
            }
        }
    }
}

public class BuilderPattern
{
}
